package com.ifnk.portaljava.dapWeb.socket;

import com.ifnk.portaljava.controller.PacketController;
import com.ifnk.portaljava.dapWeb.dapweb.Command;
import com.ifnk.portaljava.dapWeb.dapweb.SignallingPacket;
import com.ifnk.portaljava.dapWeb.hlyt.servlet.CallTraceServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

public class ProcessRawDataAll extends ProcessRawData {

    private static Log loger = LogFactory.getLog(ProcessRawDataAll.class);

    private static final String CDRKEY = "all";
    private static String pcapfilepath;
    private static String pcapNativeFile;
    private static String fileSeparator;
    private String clientId;

    private static SignallingPacket signallingPacket;


    static {
        Locale locale = Locale.ENGLISH;
        ResourceBundle localResource = ResourceBundle.getBundle("Socket",
                locale);
        pcapfilepath = localResource.getString("pacpfilepath");
        pcapNativeFile = localResource.getString("pcapNativeFile");
        fileSeparator = localResource.getString("separator");

        signallingPacket = new SignallingPacket();

    }


    public ProcessRawDataAll(ClientProperty cp, String clientId) {
        super(cp);
        this.clientId = clientId;
    }

    public void processPkt(byte[] packet) {
        try {

            int xdrLen = CallTraceServlet.getXdrLen();
            if (xdrLen == 16 || CallTraceServlet.getXdrLen() == 17) {
                command.DecodeRawDataIII(packet);
            } else {
                command.DecodeRawDataII(packet);
            }

            if (command.getCdrEndFlag() == 1) {
//				flag = false;
                loger.info("WebServer receive the CDR's CdrEndFlag=1");
            }


            if (cp.getRequestDateFromProxyId().equals(command.getSessionId())) {

                processCDRPacket(command, cp);

            } else {
                loger.error("WebServer sessionId not current client sessionId");
            }
        } catch (Exception e) {
            loger.error("WebServer Exception " + e.toString());
            loger.error("WebServer Exception CdrEndFlag: "
                    + command.getCdrEndFlag());
            e.printStackTrace();
        }

    }

    public void deleteSessionFiles() {
        String rawrootroot = pcapNativeFile + cp.getRequestDateFromProxyId();

        String pcaprootroot = pcapfilepath + "summary" + fileSeparator + cp.getRequestDateFromProxyId();

        deleteFile(new File(rawrootroot));
        deleteFile(new File(pcaprootroot));


    }

    public static void deleteSessionFilesUtil(String sessionId) {

        String rawrootroot = pcapNativeFile + sessionId;

        String pcaprootroot = pcapfilepath + "summary" + fileSeparator + sessionId;
        String pcapdetailedroot = pcapfilepath + "detailed" + fileSeparator + sessionId;

        deleteFile(new File(rawrootroot));
        deleteFile(new File(pcaprootroot));
        deleteFile(new File(pcapdetailedroot));

    }

    private static boolean deleteFile(File file) {
//		File file = new File(fileName);
        boolean flag = true;
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] children = file.listFiles();
                for (int i = 0; i < children.length; i++) {
                    flag = flag && deleteFile(children[i]);
                }
            }
            flag = flag && file.delete();
        }
        return flag;
    }


    // 将 pcaket 二进制转成文件
    private void processCDRPacket(Command command, ClientProperty cp) {


        byte buf[] = command.getPkt();

        short lenthy = (short) (((buf[0] & 0x000000ff) << 8) + (buf[1] & 0x000000ff));

        System.out.println("buf.length" + buf.length);

        if ((buf.length - 2) == lenthy) { //sdtp header

            loger.info("we got a sdtp header...");

            byte ltepkt[];

            if ((buf[3] == 0x07 && buf[2] != 0x10) || buf[3] == 0x03) {

                ltepkt = buildLtePkt(buf, (byte) 0x04, false, false);

            } else if (buf[3] == 0x01) { // 2M ss7
                ltepkt = buildLtePkt(buf, (byte) 0x8c, true, true);

            } else if (buf[3] == 0x02) { // 64k ss7
                ltepkt = buildLtePkt(buf, (byte) 0x8c, false, true);

            } else if (buf[3] == 0x06 || (buf[2] == 0x10 && buf[3] == 0x07)) {

                ltepkt = buildSoftpPkt(buf);

            } else {
                ltepkt = new byte[0];
            }

            command.setPkt(ltepkt);

        }


        if (cp.getCh().add(command)) {
            // 处理pkt
            String rawroot = pcapNativeFile + cp.getRequestDateFromProxyId() + fileSeparator + CDRKEY;

            String rawDataFileName = rawroot + fileSeparator + command.getCdrId() + "_" + command.getSequenceNo() + ".dat";
            try {
                // 写入dat 文件
                savePacketToNativeFile(rawDataFileName, rawroot, command.getPkt(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }


            String pcaproot = pcapfilepath + "summary" + fileSeparator + cp.getRequestDateFromProxyId()
                    + fileSeparator + CDRKEY;

            byte[] packet;
            String pcapFileName = pcaproot + fileSeparator + CDRKEY + ".pcap";

            // it is necessary to make a who new pacap file or just append???


            byte[] pkt = command.getPkt();
            System.out.println("command.getPkt = " + Arrays.toString(pkt));
            System.out.println("clientId = " + clientId);
            List<byte[]> byteList = PacketController.pktByteMap.get(clientId);
            if (byteList != null) {
                System.out.println("byteList = " + byteList);
                PacketController.pktByteMap.get(clientId).add(pkt);
            } else {
                PacketController.pktByteMap.put(clientId, new ArrayList<>(Collections.singleton(pkt)));
                System.out.println("byteList + " );
            }
            if (new File(pcapFileName).exists()) {
                packet = signallingPacket.TransformToDataPacket(command.getPkt());
            } else {
                packet = signallingPacket.convertPacketToPcap(command.getPkt());
            }
            System.out.println("clientId = " + clientId);

//            try {
//                // todo 多次写入 pcap 文件(追加)
//                savePacketToNativeFile(pcapFileName, pcaproot, packet, true);
//            } catch (IOException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }

            // notify the TShark thread to send the pcap file
            if (command.getPkt() != null && (command.getPkt()[7] & 0x4) == 0x4) {
                cp.cdrPktInfoMap.get(CDRKEY).setTsharkArgu("-o mtp2.use_extended_sequence_numbers:TRUE -o mtp3.heuristic_standard:TRUE");
            } else {
                cp.cdrPktInfoMap.get(CDRKEY).setTsharkArgu("-o mtp2.use_extended_sequence_numbers:FALSE -o mtp3.heuristic_standard:FALSE");
            }
            cp.cdrPktInfoMap.get(CDRKEY).setPktIndex(cp.cdrPktInfoMap.get(CDRKEY).getPktIndex() + 1);
        }
    }

    private byte[] buildSoftpPkt(byte[] buf) {
        byte[] ltepkt;
        ltepkt = new byte[buf.length - 2 + 20];

        System.arraycopy(buf, 2, ltepkt, 20, buf.length - 2);

        ltepkt[5] = 0x09; //sub type

        ltepkt[12] = buf[6 - 2];
        ltepkt[13] = buf[7 - 2];
        ltepkt[14] = buf[8 - 2];
        ltepkt[15] = buf[9 - 2];

        ltepkt[16] = buf[10 - 2];
        ltepkt[17] = buf[11 - 2];
        ltepkt[18] = buf[12 - 2];
        ltepkt[19] = buf[13 - 2];

        int length = 0;
        int len = ltepkt.length;
        if (len % 4 == 0) {
            length = len / 4;
        } else {
            length = len / 4 + 1;
        }
        ltepkt[2] = (byte) (length >> 8 & 0xFF);
        ltepkt[3] = (byte) (length >> 0 & 0xFF);
        ltepkt[7] = (byte) (length * 4 - len);

        return ltepkt;
    }

    private byte[] buildLtePkt(byte[] buf, byte linktype, boolean is2M, boolean noneip) {
        byte[] ltepkt;

        if (noneip) {
            ltepkt = new byte[buf.length - 14 + 20 - 8];
            System.arraycopy(buf, 14 + 8, ltepkt, 20, buf.length - 14 - 8);
        } else {
            ltepkt = new byte[buf.length - 14 + 20 + 2];
            System.arraycopy(buf, 14, ltepkt, 22, buf.length - 14);
        }

        //softlte[] = 0x08;
        ltepkt[5] = linktype;

        ltepkt[12] = buf[2 + 4];
        ltepkt[13] = buf[2 + 5];
        ltepkt[14] = buf[2 + 6];
        ltepkt[15] = buf[2 + 7];

        ltepkt[16] = buf[2 + 8];
        ltepkt[17] = buf[2 + 9];
        ltepkt[18] = buf[2 + 10];
        ltepkt[19] = buf[2 + 11];

        int length = 0;
        int len = ltepkt.length;
        if (len % 4 == 0) {
            length = len / 4;
        } else {
            length = len / 4 + 1;
        }
        ltepkt[2] = (byte) (length >> 8 & 0xFF);
        ltepkt[3] = (byte) (length >> 0 & 0xFF);
        ltepkt[7] = (byte) (length * 4 - len);

        if (is2M) ltepkt[7] = (byte) (ltepkt[7] | (byte) 0x10);

        return ltepkt;
    }


    public void savePacketToNativeFile(String name, String path,
                                        byte[] pkt, boolean append) throws IOException {
        System.out.println("write byte: " + pkt.length + " to file " + name);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        DataOutputStream output = new DataOutputStream(new FileOutputStream(
                new File(name), append));
        output.write(pkt);
        output.flush();
        output.close();

    }


}
